export const enum LexerTokenType {
  ROOT,
  ROOT_END,
  NUMBER,
  PAR_START,
  PAR_END,
  OPERATOR,
  EOF,
  FUNCTION,
  FUNCTION_END,
  DATA,
  COMMA,
  NEGATE,
}

export abstract class LexerToken {
  abstract type: LexerTokenType;
  abstract level: number;
  value: string;
  oppostie?: LexerTokenType;
  isConvergenced = true;
  constructor(value: string) {
    this.value = value;
  }
}

export class RootToken extends LexerToken {
  type = LexerTokenType.ROOT;
  oppostie = LexerTokenType.ROOT_END;
  level = 0;
  constructor() {
    super("ROOT");
  }
}

export class NumberToken extends LexerToken {
  type = LexerTokenType.NUMBER;
  level = 5;
}

export class ParStartToken extends LexerToken {
  type = LexerTokenType.PAR_START;
  oppostie = LexerTokenType.PAR_END;
  level = 1;
  isConvergenced = false;
  constructor() {
    super("(");
  }
}

export class ParEndToken extends LexerToken {
  type = LexerTokenType.PAR_END;
  oppostie = LexerTokenType.PAR_START;
  level = 6;
  constructor() {
    super(")");
  }
}

export class OperatorToken extends LexerToken {
  type = LexerTokenType.OPERATOR;
  level: number;
  constructor(value: string, level: number) {
    super(value);
    this.level = level;
  }
}

export class EOFToken extends LexerToken {
  type = LexerTokenType.EOF;
  level = 7;
}

export class CommaToken extends LexerToken {
  type = LexerTokenType.COMMA;
  level = 7;
}

export class NegateToken extends LexerToken {
  type = LexerTokenType.NEGATE;
  level = 4;
  constructor() {
    super("NEGATE");
  }
}

export class DataToken extends LexerToken {
  type = LexerTokenType.DATA;
  level = 5;
}

export class FunctionToken extends LexerToken {
  type = LexerTokenType.FUNCTION;
  oppostie = LexerTokenType.FUNCTION_END;
  level = 1;
  isConvergenced = false;
}
